//author Sylvain Bertrand <digital.ragnarok@gmail.com>
//Protected by GNU Affero GPL v3 with some exceptions.
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/mman.h>
#include <error.h>
#include <errno.h>

#include <linux/types.h>

#include <alga/pixel_fmts.h>
#include <alga/amd/dce6/dce6.h>
#include <alga/amd/si/ioctl.h>

#define e(m,...) error(0,0,m,##__VA_ARGS__)
#define o(m,...) printf(m,##__VA_ARGS__)
#define unsignedl unsigned long

#define EDID_SZ_MAX ((255 + 1) * 128)
int main(void)
{
  int r0=0;
  //incomplete arrays count for a 1 element array size in sizeof operator
  void *edid=malloc(EDID_SZ_MAX);
  if(!edid){
    e("unable to alloc max edid mem\n");
    r0=EXIT_FAILURE;
    goto exit;
  }

  struct si_dce_edid ioctl_edid;
  ioctl_edid.edid_sz=0;
  do{
    //stdin is a blocking fd
    r0=(int)read(0,edid+ioctl_edid.edid_sz,EDID_SZ_MAX-ioctl_edid.edid_sz);
    if(r0==-1)
      switch(errno){
      case EINTR:
        continue;//start over the read
      default:
        e("an error occured when reading edid on stdin\n");
        r0=EXIT_FAILURE;
        goto exit;
      }
    ioctl_edid.edid_sz+=r0;//account for the read bytes
  }while(r0);//till the end of the file

  ioctl_edid.edid=edid;

  int f=open("/dev/si0", O_RDWR);
  if(f==-1){
    e("open failed\n");
    r0=EXIT_FAILURE;
    goto exit;
  }

  ioctl_edid.idx=4;
  unsignedl req=_IOW('d',SI_DCE_EDID,ioctl_edid);
  r0=ioctl(f,req,&ioctl_edid);
  if(r0==-1){
    r0=EXIT_FAILURE;
    e("edid failed %u\n",errno);
  }
exit:
  return r0;
}
